package it.poste.il.compensatore.datamanager.impl;

import it.poste.il.compensatore.dao.MessageBodyDao;
import it.poste.il.compensatore.dao.MessageDao;
import it.poste.il.compensatore.dao.MessageStatusDao;
import it.poste.il.compensatore.dao.OperationDao;
import it.poste.il.compensatore.dao.SDPRequestDao;
import it.poste.il.compensatore.datamanager.DataManager;
import it.poste.il.compensatore.entities.Message;
import it.poste.il.compensatore.entities.MessageBody;
import it.poste.il.compensatore.entities.MessageStatus;
import it.poste.il.compensatore.entities.Operation;
import it.poste.il.compensatore.entities.SDPRequest;
import it.poste.il.compensatore.utilities.LogFactory;
import it.poste.il.compensatore.utilities.LoggerCompensatore;

import java.rmi.RemoteException;
import java.util.List;

import org.apache.log4j.Logger;

public class DataManagerImpl implements DataManager {
	
	private LogFactory loggerF;

	private MessageBodyDao messageBodyDao;
	private OperationDao operationDao;
	private MessageStatusDao messageStatusDao;
	private MessageDao messageDao;
	private SDPRequestDao sdpRequestDao;

	
	public LogFactory getLoggerF() {
		return loggerF;
	}

	public void setLoggerF(LogFactory loggerF) {
		this.loggerF = loggerF;
	}

	public MessageBodyDao getMessageBodyDao() {
		return messageBodyDao;
	}

	public void setMessageBodyDao(MessageBodyDao messageBodyDao) {
		this.messageBodyDao = messageBodyDao;
	}

	public OperationDao getOperationDao() {
		return operationDao;
	}

	public void setOperationDao(OperationDao operationDao) {
		this.operationDao = operationDao;
	}

	public MessageStatusDao getMessageStatusDao() {
		return messageStatusDao;
	}

	public void setMessageStatusDao(MessageStatusDao messageStatusDao) {
		this.messageStatusDao = messageStatusDao;
	}

	public MessageDao getMessageDao() {
		return messageDao;
	}

	public void setMessageDao(MessageDao messageDao) {
		this.messageDao = messageDao;
	}

	public SDPRequestDao getSdpRequestDao() {
		return sdpRequestDao;
	}

	public void setSdpRequestDao(SDPRequestDao sdpRequestDao) {
		this.sdpRequestDao = sdpRequestDao;
	}

	public DataManagerImpl() throws RemoteException {
		super();
		// TODO Auto-generated constructor stub
	}
	//	private final LoggerCompensatore logger = new LoggerCompensatore(this.getClass().getName());
	
	/**
	 * Metodo storeMsg.
	 * Restituisce il nuovo message Id generato.
	 * @return valore del messageId;
	 */
	public MessageBody storeMsg(String msg, SDPRequest requestId){
		Message message = new Message();
		Logger logger=loggerF.getLogger(this);
		//SDPRequest
		logger.info("setta la requestId");
		SDPRequest sdpRequest = sdpRequestDao.save(requestId);
		logger.info("requestId salvata " + sdpRequest.getId());
		message.setSdpRequestId(requestId);
		
		//tipo dritta
		logger.debug("setta il tipo di messaggio dritto");
		message.setType(0);
		
		logger.debug("legge l'operation e l'associa al msg");
		//Operation
		Operation opList = operationDao.loadById(2000L);
		logger.debug("*******************************classe " + opList.getObjHelper());
		message.setOperationId(opList);

		logger.debug("configura il messge status");
		//MessageStatus 1 = invio in corso
		MessageStatus messageStatus = messageStatusDao.loadById(1000L);
//		messageStatus.setDescription("invio in corso");
		message.setStatusId(messageStatus);
		
		logger.debug("message da salvare");
		message = messageDao.save(message);
		logger.debug("message salvato " + message.getType() +" " + message.getId());
		
		logger.debug("crea il messge body");
		//MessageBody
		MessageBody messageBody = new MessageBody();
		logger.debug("associo il messaggio");
		messageBody.setInputMessage(msg);
		logger.debug("associo la classe message");
		messageBody.setMessage(message);
		logger.debug(" classe message associata al msgbody");

		messageBody = messageBodyDao.save(messageBody);
		logger.debug("message body salvato");
		return messageBody;
	}
		
	/**
	 * Metodo verifyRequest.
	 * Restituisce l'esito della verifica. 1 se non duplicato, 2 se da annullare, 3 se da riallineare
	 * @return esito verifica;
	 */
	public String verifyRequest(SDPRequest requestId, String fase){
		
		SDPRequest req = new SDPRequest();
		Logger logger=loggerF.getLogger(this);

		logger.info("inizio verifica");
		
		//entity SDPRequest senza la count
		req.setAccountingDate(requestId.getAccountingDate());
		req.setBranch(requestId.getBranch());
		req.setNumberOperationPdl(requestId.getNumberOperationPdl());
		req.setWorkingStationId(requestId.getWorkingStationId());
		
		//message con associata la SDPRequest req
		Message msg = new Message();
		msg.setSdpRequestId(req);
		
		logger.info("preparato msg con requestid");
		
		//stato del messaggio ad eseguito
		MessageStatus msgStatus = new MessageStatus();
		msgStatus.setId(1002L);
		msg.setStatusId(msgStatus);
		logger.info("preparato msg con stato ad ESEGUITO");
		
		//tipo del messaggio dritto
		msg.setType(1);
		logger.info("preparato msg con tipo dritto");
		
	
		logger.info("caricamento l'ultimo lavorato con la nuova query");
		
		List<SDPRequest> sdpReqNew = sdpRequestDao.loadLastCounter(req);
		logger.info("nuova query");
		logger.info("nuova query count resultset"+ sdpReqNew.size());
//		logger.info("**** primo id " + sdpReqNew.get(0).getId());
		
		//legge il progressivo dell'ultima richiesta elaborata
		
		int counter=0;
		if(sdpReqNew.size()!=0){
			sdpReqNew.get(0).getCounter();
		}
		
		//contatore del messaggio ricevuto da SDP
		int counterRequest = requestId.getCounter();
		logger.info("counter messaggio ricevuto "+ counterRequest);
		
		//cambiare tipo di ritorno
		if(fase.equals("D")){//DISPOSITIVA
			if(counterRequest==counter+1){
				logger.info("elabora");
				return "E";
			} else if(counterRequest == counter){
				logger.info("annulla");
				return sdpReqNew.get(0).getId().toString();
			} else if(counterRequest < counter || counterRequest > counter+1){
				logger.info("riallinea");
				return "R";
			}
		} else {// INFORMATIVA
			if(counterRequest==counter){
				logger.info("elabora");
				//ok elabora
				return "E";
			} else if(counterRequest == counter-1){
				logger.info("annulla");
				//ANNULLA counter
				return sdpReqNew.get(0).getId().toString();
			} else if(counterRequest < counter-1 || counterRequest > counter){
				logger.info("riallinea");
				//RIALLINEA
				return "R";
			}
			
		}
			
		return "0";
	
	}
	
	
	/**
	 * Metodo createAvoidMessage.
	 * Restituisce il messaggio di annullamento per la richiesta requestId.
	 * @return messaggio di annullamento;
	 */
	public String createAvoidMessage(String requestId){
		return "avoid";
	}
	
	/**
	 * Metodo changeStatus.
	 * Cambia lo stato del messaggio.
	 * @param il messaggio a cui aggiornare lo stato, il nuovo stato
	 * @return l'esito dell'aggiornamento
	 */
	public boolean changeStatus(Message message, Long status){
		MessageStatus newStatus = new MessageStatus();
		newStatus.setId(status);
		message.setStatusId(newStatus);
		messageDao.update(message);
		return true;
	}
	
}
